package com.dtguai.app.interceptor;


import com.dtguai.app.annotation.Login;
import com.dtguai.app.common.context.BaseContext;
import com.dtguai.app.common.error.ErrorCode;
import com.dtguai.app.common.exception.DefinedException;
import com.dtguai.app.util.JwtUtils;
import io.jsonwebtoken.Claims;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Optional;

/**
 * 权限(Token)验证
 *
 * @author guo
 * @date 2019年2月14日15:55:39
 */
@Component
@Slf4j
@AllArgsConstructor
public class AuthorizationInterceptor extends HandlerInterceptorAdapter {

    private final JwtUtils jwtUtils;

    public static final String USER_KEY = "userId";

    /**
     * 1  preHandle在业务处理器处理请求之前被调用
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {

        if (handler instanceof HandlerMethod) {
            //判断是否有login注解
            Optional.ofNullable(((HandlerMethod) handler)
                    .getMethodAnnotation(Login.class))
                    .ifPresent(x -> verifyToken(request));
        }
        return true;
    }

    private String getHeader(HttpServletRequest request) {
        String sign = request.getHeader(JwtUtils.TOKEN_HEADER);
        if (StringUtils.isBlank(sign)) {
            sign = request.getParameter(JwtUtils.TOKEN_HEADER);
        }
        return sign;
    }

    private void verifyToken(HttpServletRequest request) {

        //获取用户凭证
        String token = getHeader(request);

        //凭证为空
        token = Optional.ofNullable(token)
                .orElseThrow(() -> new DefinedException(JwtUtils.TOKEN_HEADER + "不能为空", ErrorCode.BAD_REQUEST.getCode()));

        Claims claims = jwtUtils.getClaimByToken(token);
        if (claims == null) {
            throw new DefinedException(ErrorCode.TOKEN_VALIDATE_ERROR);
        }
        else if (jwtUtils.isTokenExpired(claims.getExpiration())) {
            throw new DefinedException(ErrorCode.TOKEN_EXPIRED);
        }

        BaseContext.setUserId(Integer.parseInt(claims.getSubject()));
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        BaseContext.remove();
        try {
            super.afterCompletion(request, response, handler, ex);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

}
